package cn.unknowpupil.init.service.system.impl;

import cn.unknowpupil.init.common.constant.SecurityConstants;
import cn.unknowpupil.init.domain.dto.LoginUser;
import cn.unknowpupil.init.domain.dto.MenuNode;
import cn.unknowpupil.init.domain.dto.MetaVo;
import cn.unknowpupil.init.domain.system.SysMenu;
import cn.unknowpupil.init.domain.system.SysUser;
import cn.unknowpupil.init.domain.dto.TreeSelect;
import cn.unknowpupil.init.service.system.ISysMenuService;
import cn.unknowpupil.init.mapper.system.SysMenuMapper;
import cn.unknowpupil.init.utils.security.SecurityUtils;
import cn.unknowpupil.init.utils.strings.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created at 2020-11-13 by  w10g <br>
 * Initialize SysMenu  ... <br>
 * 菜单表 核心业务处理实现类
 *
 * @author unknowpupil
 * @since 0.0.1
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {


    /**
     * 新增
     *
     * @param sysMenu {@link SysMenu}  菜单表
     * @return {@link SysMenu}
     */
    @Override
    public boolean create(SysMenu sysMenu) {
        if (sysMenu.getPid() != null && sysMenu.getPid() > 0) {
            SysMenu parent = baseMapper.selectById(sysMenu.getPid());
            sysMenu.setFullId(parent.getFullId() + '-' + parent.getId());
        } else {
            sysMenu.setFullId("0");
        }
        return save(sysMenu);
    }

    /**
     * 详情
     *
     * @param id {@code Long}   SysMenu ID
     * @return {@link SysMenu}
     */
    @Override
    public SysMenu info(Long id) {

        return getById(id);
    }

    /**
     * 删除
     *
     * @param menuId {@code Long}   SysMenu ID
     * @return {@link SysMenu}
     */
    @Override
    public boolean delete(Long menuId) {
        Assert.isTrue(!hasChildByMenuId(menuId), "存在子菜单,不允许删除");
        return removeById(menuId);
    }

    /**
     * 是否存在菜单子节点
     *
     * @param menuId 菜单ID
     * @return 结果
     */
    public boolean hasChildByMenuId(Long menuId) {
        Integer result = baseMapper.selectCount(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getPid, menuId));
        return result > 0 ? true : false;
    }


    /**
     * 修改
     *
     * @param sysMenu {@link SysMenu}  菜单表
     * @return {@link SysMenu}
     */
    @Override
    public boolean update(SysMenu sysMenu) {
        if (sysMenu.getPid() != null && sysMenu.getPid() > 0) {
            SysMenu parent = baseMapper.selectById(sysMenu.getPid());
            sysMenu.setFullId(parent.getFullId() + '-' + parent.getId());
        } else {
            sysMenu.setFullId("0");
        }
        return updateById(sysMenu);
    }


    @Override
    public List<MenuNode> selectMenuTreeByUserId(LoginUser loginUser) {

        List<SysMenu> resList = null;
        if (SecurityUtils.isAdmin(loginUser.getPid())) {
            resList = baseMapper.selectMenuTreeAll();
        } else {
            resList = baseMapper.selectMenuTreeByUserId(loginUser.getId());
        }
        List<MenuNode> treeList = new ArrayList<>();
        MenuNode newNode;
        for (SysMenu node : resList) {
            if (node.getPid() == 0) {
                newNode = new MenuNode(node.getId(), node.getPid(), StringUtils.capitalize(node.getPath()));

                MetaVo metaVo = new MetaVo(node.getName(), node.getIconClass(), node.getIsCache().equals("1"));
                newNode.setMeta(metaVo);

                newNode.setRedirect(SecurityConstants.NO_REDIRECT);
                newNode.setComponent("Layout");
                newNode.setAlwaysShow(true);
                newNode.setPath("/" + node.getPath());
                newNode.setHidden(node.getHiddenFlag().equals(1 + "") ? true : false);
                treeList.add(findChildrenWithAuth(newNode, resList));
            }
        }

        return treeList;

    }

    @Override
    public List<SysMenu> selectMenuList(SysMenu menu, LoginUser loginUser) {
        List<SysMenu> menuList = null;
        // 管理员显示所有菜单信息
        if (SysUser.isAdmin(loginUser.getPid())) {
            LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
            if (StringUtils.isNotBlank(menu.getName())) {
                wrapper.like(SysMenu::getName, menu.getName());
            }
            if (StringUtils.isNotBlank(menu.getStatus())) {
                wrapper.eq(SysMenu::getStatus, menu.getStatus());
            }
            wrapper.orderByAsc(SysMenu::getPid, SysMenu::getShowOrder);

            menuList = baseMapper.selectList(wrapper);
        } else {
            menuList = baseMapper.selectMenuListByUserId(menu, loginUser.getId());
        }
        return menuList;
    }

    @Override
    public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus) {
        List<SysMenu> menuTrees = buildMenuTree(menus);
        return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 构建前端所需要树结构
     *
     * @param menus 菜单列表
     * @return 树结构列表
     */
    public List<SysMenu> buildMenuTree(List<SysMenu> menus) {
        List<SysMenu> returnList = new ArrayList<SysMenu>();
        List<Long> tempList = new ArrayList<Long>();
        for (SysMenu dept : menus) {

            tempList.add(dept.getId());
        }
        for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext(); ) {
            SysMenu menu = (SysMenu) iterator.next();
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(menu.getPid())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionFn(List<SysMenu> list, SysMenu t) {
        // 得到子节点列表
        List<SysMenu> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysMenu tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private boolean hasChild(List<SysMenu> list, SysMenu tChild) {
        return getChildList(list, tChild).size() > 0 ? true : false;
    }

    /**
     * 得到子节点列表
     */
    private List<SysMenu> getChildList(List<SysMenu> list, SysMenu menu) {
        List<SysMenu> tlist = new ArrayList<SysMenu>();
        Iterator<SysMenu> it = list.iterator();
        while (it.hasNext()) {
            SysMenu n = (SysMenu) it.next();
            if (n.getPid().longValue() == menu.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 递归构造树结构
     *
     * @param parentNode
     * @param resList
     * @return
     */
    private MenuNode findChildrenWithAuth(MenuNode parentNode, List<SysMenu> resList) {
        MenuNode newNode;
        for (SysMenu menu : resList) {
            if (menu.getPid().equals(parentNode.getId())) {
                if (parentNode.getChildren() == null) {
                    parentNode.setChildren(new ArrayList<>());
                }
                newNode = new MenuNode(menu.getId(), menu.getPid(), StringUtils.capitalize(menu.getPath()));
                newNode.setMeta(new MetaVo(menu.getName(), menu.getIconClass(), menu.getIsCache().equals("1")));
                newNode.setComponent(menu.getComponent());
                newNode.setPath(menu.getPath());
                newNode.setHidden(menu.getHiddenFlag().equals(1 + "") ? true : false);
                MenuNode tempNode = findChildrenWithAuth(newNode, resList);
                parentNode.getChildren().add(tempNode);
            }
        }
        return parentNode;
    }

}
